﻿#pragma once

#include "VisAlgorithm.h"

#include "visual_data.h"

class VisualCommon : public VisAlgorithm
{

public:
	VisualCommon();
	~VisualCommon();

	virtual int Init(const visAlgParam& param) override;

	virtual bool Caculate(const VisAlgInput& input, Position& pos, VisAlgOutput& out) override;


	bool InitCalibration(const QString& file);
	bool CheckParam(const VisAlgInput& input, QString& msg);
	// 获取点云
	PointCloud::Ptr GetDepthPointCloud(const QString& depfile);
	// 点云过滤操作
	PointCloud::Ptr Filter(PointCloud::Ptr cloud_in);
	// 切割箱子点云
	PointCloud::Ptr GetBoxCloud(PointCloud::Ptr cloud_in, const BoxPoint& box);
	// 创建夹具点云
	PointCloud::Ptr CreateJigCloud(int jig);
	// 点云转换到世界坐标系
	PointCloud::Ptr TranToWorld(PointCloud::Ptr cloud);
	// 点云转换到相机坐标系
	PointCloud::Ptr TransToCamera(PointCloud::Ptr cloud);
	// 点云转换到像素坐标系
	PointCloud::Ptr TransToPix(PointCloud::Ptr cloud);
	// 切割点云到托盘范围
	PointCloud::Ptr CutCloudToPlate(PointCloud::Ptr cloud);
	// 根据点云计算箱子的四个角坐标
	cv::RotatedRect MathBoxCvRect(PointCloud::Ptr cloud, int h, int w);

	// 计算箱子的位置信息
	visual::BoxInfo GetBoxInfo(PointCloud::Ptr cloud, cv::RotatedRect& rect);
	//下采样的mask上采样
	void UpsampleMask(cv::Mat mask, cv::Mat& upMask, int pad);
	// 获取最小区域轮廓
	cv::RotatedRect GetMinAreaRect(cv::Mat mask);

	void EuclideanClusterExtractionCloud(const PointCloud::Ptr& pCloud, float fClusterTolerance,
		int iMinClusterSize, int iMaxClusterSize, std::vector<PointCloud::Ptr>* pvCloudPtr);

	// 计算聚类中的最大高度
	double MathMaxCloud(std::vector<PointCloud::Ptr> vCloudPtr);

	void DrawPointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, cv::Scalar sc, cv::Mat& image);
	void DrowPlate(cv::Mat& image, double height);
	void DrowBox(cv::Mat& image, cv::RotatedRect rect);
	void DrawRcog(cv::Mat& image, std::vector<cv::Point>&);
	QByteArray ImgEncodeToByte(const cv::Mat& Image, const std::string& ext);

	// 查找抓取箱子组
	visual::BoxInfo FindGrabBoxGroup(QVector<visual::BoxInfo>& pos, int grabNum);

	// 箱子抓取顺序排序
	bool SortSkuPos(QVector<visual::BoxInfo>& pos);

	// 保持点云文件
	void SavePCDFile(const PointCloud::Ptr& pCloud, const QString& name);

private:
	QVector<QVector<float>> m_intri;	// 内参
	cv::Mat m_intriMatrix = {};	//内参
	cv::Mat m_distorMatrix = {};	//畸变系数
	QVector<QVector<float>> m_external;
	cv::Mat m_exteMatrix = {};	// 外参
	Position m_plateMin = {};
	Position m_plateMax = {};	// 托盘的坐标范围

	int m_maxNum = 1;	// 最大抓取数量
	int m_dir = -1;	// 拆垛方向 1：表示从第一象限开始拆
	bool m_save = true;
};
